﻿// This software is the confidential and proprietary information of NetBay.
// Such confidential information should not be disclosed.
// NetBay copyright(c) 2011

using System;
using System.ComponentModel;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using GalaSoft.MvvmLight.Command;
using NetBay.Core.BusinessEntities;
using NetBay.Core.Encryption.Licensing;
using Rio.Applications.Web.Services;
using Rio.Framework.Localisation;
using Rio.Framework.Pages.AppCode.Helpers;
using Rio.Framework.Pages.Context;
using Rio.Framework.Pages.Enums;
using Rio.Framework.Pages.Manager;
using Rio.Framework.Pages.Viewer;

namespace Rio.Framework.Pages.MenuOffice
{
    public partial class HeadMenu : INotifyPropertyChanged
    {
        #region Events

        public TimeoutAction CloseHomeMenuAction { get; private set; }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Fields

        private User _currentUser;
        private bool _flowIsEnabled;
        private bool _importIsEnabled;
        private bool _managerIsEnabled;
        private long _newMessagesCount;
        private DispatcherTimer _newMessagesTimer;
        private bool _scanInstallIsEnabled;
        private bool _scanIsEnabled;
        private bool _searchIsEnabled;

        #endregion

        #region Properties

        private ApplicationName _applicationName;

        public ApplicationName ApplicationName
        {
            get { return _applicationName; }
            set
            {
                _applicationName = value;
                OnPropertyChanged("ApplicationName");
            }
        }

        /// <summary>
        /// Gets a value indicating whether [notification activated].
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [notification activated]; otherwise, <c>false</c>.
        /// </value>
        public bool NotificationActivated
        {
            get
            {
                if (GlobalWebContext.RioAppSettings["FlowNotificationActivated"] != null)
                {
                    return Convert.ToBoolean(GlobalWebContext.RioAppSettings["FlowNotificationActivated"].ToString());
                }
                return false;
            }
        }

        /// <summary>
        /// Gets the notification time interval.
        /// </summary>
        public int NotificationTimeInterval
        {
            get
            {
                if (GlobalWebContext.RioAppSettings["FlowNotificationTimeInterval"] != null)
                {
                    return Convert.ToInt32(GlobalWebContext.RioAppSettings["FlowNotificationTimeInterval"].ToString());
                }
                return 1;
            }
        }


        public RelayCommand<string> ApplicationCommand { get; set; }

        public long NewMessagesCount
        {
            get { return _newMessagesCount; }
            set
            {
                _newMessagesCount = value;
                OnPropertyChanged("NewMessagesCount");
            }
        }

        public User CurrentUser
        {
            get { return _currentUser; }
            set
            {
                _currentUser = value;
                OnPropertyChanged("CurrentUser");
            }
        }

        public bool FlowIsEnabled
        {
            get { return _flowIsEnabled; }
            set
            {
                _flowIsEnabled = value;
                OnPropertyChanged("FlowIsEnabled");
            }
        }

        public bool SearchIsEnabled
        {
            get { return _searchIsEnabled; }
            set
            {
                _searchIsEnabled = value;
                OnPropertyChanged("SearchIsEnabled");
            }
        }

        public bool ImportIsEnabled
        {
            get { return _importIsEnabled; }
            set
            {
                _importIsEnabled = value;
                OnPropertyChanged("ImportIsEnabled");
            }
        }

        public bool ManagerIsEnabled
        {
            get { return _managerIsEnabled; }
            set
            {
                _managerIsEnabled = value;
                OnPropertyChanged("ManagerIsEnabled");
            }
        }

        public bool ScanIsEnabled
        {
            get { return _scanIsEnabled; }
            set
            {
                _scanIsEnabled = value;
                OnPropertyChanged("ScanIsEnabled");
            }
        }

        public bool ScanInstallIsEnabled
        {
            get { return _scanInstallIsEnabled; }
            set
            {
                _scanInstallIsEnabled = value;
                OnPropertyChanged("ScanInstallIsEnabled");
            }
        }

        #endregion

        #region Localization

        public string HomeButtonLabel { get; set; }
        public string ImportButtonLabel { get; set; }
        public string SearchButtonLabel { get; set; }
        public string FlowButtonLabel { get; set; }
        public string ManagerButtonLabel { get; set; }
        public string ScanButtonLabel { get; set; }
        public string ScanInstallButtonLabel { get; set; }
        public string HistoryButtonLabel { get; set; }
        public string DisconnectButtonLabel { get; set; }
        public string LastIndexationsLabel { get; set; }
        public string LastSearchesLabel { get; set; }
        public string LastConsultationsLabel { get; set; }
        public string SavedSearchesLabel { get; set; }

        #endregion

        #region Constructors

        public HeadMenu()
        {
            InitializeComponent();


            if (!IsInDesignMode)
            {

                InitLabels();

                CloseHomeMenuAction = new TimeoutAction(500);

                ApplicationCommand = new RelayCommand<string>(ApplicationCommandExecute, CanExecuteApplicationCommand);
            }
        }

        #endregion

        private void InitLabels()
        {
            HomeButtonLabel = Resx.GetLabel(ResxMenu.HOME);
            ManagerButtonLabel = Resx.GetLabel(ResxMenu.MANAGER);
            FlowButtonLabel = Resx.GetLabel(ResxMenu.FLOW);
            ImportButtonLabel = Resx.GetLabel(ResxMenu.INDEX);
            SearchButtonLabel = Resx.GetLabel(ResxMenu.SEARCH);
            ScanButtonLabel = Resx.GetLabel(ResxMenu.SCAN);
            ScanInstallButtonLabel = Resx.GetLabel(ResxMenu.SCAN_INSTALL);
            DisconnectButtonLabel = Resx.GetLabel(ResxMenu.DECONNECTION);
            HistoryButtonLabel = Resx.GetLabel(ResxHistoric.HISTORIC);
            LastIndexationsLabel = Resx.GetLabel(ResxHistoric.HISTORIC_LAST_INDEXATIONS);
            LastSearchesLabel = Resx.GetLabel(ResxHistoric.HISTORIC_LAST_SEARCHES);
            LastConsultationsLabel = Resx.GetLabel(ResxHistoric.HISTORIC_LAST_CONSULTATIONS);
            SavedSearchesLabel = Resx.GetLabel(ResxHistoric.HISTORIC_SAVED_SEARCHES);
        }

        private void InitializeNewMessagesTimer()
        {
            _newMessagesTimer = new DispatcherTimer
                                    {
                                        Interval = new TimeSpan(0, NotificationTimeInterval, 0)
                                    };
            _newMessagesTimer.Tick += _newMessagesTimer_Tick;
            StartNotification();
        }

        private void _newMessagesTimer_Tick(object sender, EventArgs e)
        {
            CheckNewMessages();
        }

        /// <summary>
        /// Starts the notification.
        /// </summary>
        public void StartNotification()
        {
            if (_newMessagesTimer != null)
                _newMessagesTimer.Start();
        }

        /// <summary>
        /// Suspends the notification.
        /// </summary>
        public void SuspendNotification()
        {
            if (_newMessagesTimer != null)
                _newMessagesTimer.Stop();
        }


        private void userControl_Unloaded(object sender, RoutedEventArgs e)
        {
            if (_newMessagesTimer != null)
            {
                _newMessagesTimer.Stop();
                _newMessagesTimer.Tick -= _newMessagesTimer_Tick;
                _newMessagesTimer = null;
            }
        }

        private bool CanExecuteApplicationCommand(string param)
        {
            bool result = false;

            switch (param.ToLowerInvariant())
            {
                case "home":
                    result = ApplicationName != ApplicationName.RioOffice;
                    break;
                case "import":
                    result = ApplicationName != ApplicationName.RioImport;
                    break;
                case "search":
                    result = ApplicationName != ApplicationName.RioSearch;
                    break;
                case "flow":
                    result = ApplicationName != ApplicationName.RioFlow;
                    break;
                case "manager":
                    result = ApplicationName != ApplicationName.RioManager;
                    break;
                case "configuration":
                case "installation":
                case "disconnect":
                    result = true;
                    break;
            }

            return result;
        }

        private void ApplicationCommandExecute(string param)
        {
            Cursor = Cursors.Wait;

            switch (param.ToLowerInvariant())
            {
                case "home":
                    Redirection.RioOffice();
                    break;
                case "import":
                    Redirection.RioImport();
                    break;
                case "search":
                    Redirection.RioSearch();
                    break;
                case "flow":
                    Redirection.RioFlow();
                    break;
                case "manager":
                    Redirection.RioManager();
                    break;
                case "configuration":
                    Redirection.RioScan("B");
                    break;
                case "installation":
                    ScanInstall scanInstallWindow = new ScanInstall();
                    scanInstallWindow.Show();
                    Cursor = Cursors.Arrow;
                    break;
                case "disconnect":
                    LoginManager.Instance.LogOut();
                    break;
            }
        }

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region Check New Messages

        /// <summary>
        /// Checks the new messages.
        /// </summary>
        private void CheckNewMessages()
        {
            _newMessagesCount = 0;
            BusinessEntitiesDomainContext ds = GlobalWebContext.BusinessEntitiesDomainContext;

            var countMessageFlowInMyBoxQuery = ds.CountMessageFlowInMyBoxQuery();
            ds.Load(countMessageFlowInMyBoxQuery, OnGetMessageFlowInMyBoxCallback, null);
        }

        /// <summary>
        /// Called when [get message flow in my box callback].
        /// </summary>
        /// <param name="result">The result.</param>
        private void OnGetMessageFlowInMyBoxCallback(LoadOperation<ReturnLong> result)
        {
            if(result.Entities != null && result.Entities.Count() > 0 && result.Entities.First().IsValid)
            {
                _newMessagesCount += result.Entities.First().Value;
            }

            CheckMessageFlowSentByMe();
        }

        /// <summary>
        /// Checks the message flow sent by me.
        /// </summary>
        private void CheckMessageFlowSentByMe()
        {
            BusinessEntitiesDomainContext ds = GlobalWebContext.BusinessEntitiesDomainContext;
            var countMessageFlowSentByMeQuery = ds.CountMessageFlowSentByMeQuery();
            ds.Load(countMessageFlowSentByMeQuery, OnGetMessageFlowSentByMeCallback, null);
        }

        /// <summary>
        /// Called when [get message flow sent by me callback].
        /// </summary>
        /// <param name="result">The result.</param>
        private void OnGetMessageFlowSentByMeCallback(LoadOperation<ReturnLong> result)
        {
            if (result.Entities != null && result.Entities.Count() > 0 && result.Entities.First().IsValid)
            {
                _newMessagesCount += result.Entities.First().Value;
            }

            if (GlobalWebContext.LicenseTerms.LicenseType == LicenseType.Enterprise)
            {
                CheckWorkflowMessages();
            }
            else
            {
                UpdateNewMessagesCount();
            }
        }

        /// <summary>
        /// Checks the workflow messages.
        /// </summary>
        private void CheckWorkflowMessages()
        {
            BusinessEntitiesDomainContext ds = GlobalWebContext.BusinessEntitiesDomainContext;
            var getWorkflowInstancesByUserIdQuery = ds.GetWorkflowInstanceNotReadQuery();
            ds.Load(getWorkflowInstancesByUserIdQuery, OnGetWorkflowInstancesByUserIdCallback, null);
        }

        /// <summary>
        /// Called when [get workflow instances by user id callback].
        /// </summary>
        /// <param name="result">The result.</param>
        private void OnGetWorkflowInstancesByUserIdCallback(LoadOperation<ReturnLong> result)
        {
            if (!result.HasError
                && result.Entities.Count() > 0)
            {
                _newMessagesCount += Convert.ToInt32(result.Entities.First().Value);
            }

            UpdateNewMessagesCount();
        }

        /// <summary>
        /// Updates the new messages count.
        /// </summary>
        private void UpdateNewMessagesCount()
        {
            NewMessagesCount = _newMessagesCount;
            newMessagesButton.Visibility = (FlowIsEnabled && NewMessagesCount == 0)
                                               ? Visibility.Collapsed
                                               : Visibility.Visible;
        }

        #endregion

        #region User Rights

        public void LoadUser(ApplicationName applicationName)
        {
            CurrentUser = GlobalWebContext.CurrentUser;

            CheckUserPriviledges();

            CheckNewMessages();

            if (NotificationActivated)
                InitializeNewMessagesTimer();

            ApplicationName = applicationName;
            ApplicationCommand.RaiseCanExecuteChanged();
        }

        private void CheckUserPriviledges()
        {
            foreach (Group grp in CurrentUser.GroupList)
            {
                if (grp.IsAdministrator)
                {
                    ImportIsEnabled = true;
                    SearchIsEnabled = true;
                    FlowIsEnabled = GlobalWebContext.LicenseTerms.LicenseType == LicenseType.Enterprise;
                    ManagerIsEnabled = true;
                    ScanInstallIsEnabled = true;
                    LoadScan();

                    break;
                }

                // Active scan/import right
                if (grp.CanScann)
                {
                    ImportIsEnabled = true;
                    SearchIsEnabled = false;
                    ManagerIsEnabled = false;
                    ScanInstallIsEnabled = true;
                    LoadScan();
                }

                // Active search right.
                if ((grp.CanConsult) || (grp.CanReorganize) || (grp.CanDownload) || (grp.CanPrint)
                    || (grp.CanSendEmail))
                {
                    ImportIsEnabled = true;
                    SearchIsEnabled = true;
                    ManagerIsEnabled = false;
                }

                //Active flow
                FlowIsEnabled = (grp.CanFlow && GlobalWebContext.LicenseTerms.LicenseType == LicenseType.Enterprise);
            }
        }

        private void LoadScan()
        {
            BusinessEntitiesDomainContext businessEntitiesDomainContext = new BusinessEntitiesDomainContext();
            businessEntitiesDomainContext.GetPcApplicationStatus("RIOSCAN",
                                                                    delegate(InvokeOperation<ReturnBoolean> retr)
                                                                    {
                                                                        if (retr != null && retr.Value != null
                                                                            && retr.Value.IsValid)
                                                                        {
                                                                            ScanIsEnabled = (retr.Value.Value);
                                                                        }
                                                                    },
                                                                    null);
        }

        #endregion
    }
}